package com.gopay.solution.manager.impl;

import com.gopay.common.cache.client.RedisClient;
import com.gopay.common.cache.constants.RedisConstants;
import com.gopay.common.cache.service.CacheCleanService;
import com.gopay.common.cache.vo.CacheClean;
import com.gopay.common.constants.Constants;
import com.gopay.common.constants.solution.SolutionTypeConstant;
import com.gopay.common.exception.validator.GopayCheckException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.FastJsonUtil;
import com.gopay.solution.common.constant.OprLevel;
import com.gopay.solution.dao.SsAcctSolutionRelDAO;
import com.gopay.solution.dao.SsApSolutionRelDAO;
import com.gopay.solution.domain.po.SolutionRuleDtl;
import com.gopay.solution.domain.po.SsAcctSolutionRel;
import com.gopay.solution.domain.po.SsApSolutionRel;
import com.gopay.solution.domain.vo.Solution;
import com.gopay.solution.manager.SolutionManager;
import com.gopay.solution.manager.SsTbSolutionManager;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@Service(value = "ssTbSolutionManager")
public class SsTbSolutionManagerImpl implements SsTbSolutionManager{
    private  final Logger logger = LoggerFactory.getLogger(getClass());
    
    @Resource(name = "ssTransBasicSoluManager")
    private SolutionManager ssTransBasicSoluManager;
    
    @Resource(name="ssApSolutionRelDAO")
    private SsApSolutionRelDAO ssApSolutionRelDAO;
    
    @Resource(name = "ssAcctSolutionRelDAO")
    private SsAcctSolutionRelDAO ssAcctSolutionRelDAO;

    @Autowired
    RedisConstants redisConstants;

    @Resource(name = "cacheCleanService")
    private CacheCleanService cacheCleanService;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class, RuntimeException.class })
    public void editSsTbSolution(long solutionId, String gopayIntTxnCd, List<SolutionRuleDtl> rules,String prodCode) throws GopayCheckException {
        
        if(solutionId < 0 || StringUtils.isEmpty(gopayIntTxnCd) || rules == null) {
            throw new GopayCheckException("", "传入数据有误，操作失败");
        }
        
        Solution solu = ssTransBasicSoluManager.loadBySeqAndIntTxnCd(solutionId, gopayIntTxnCd);
        if(solu == null) {
            throw new GopayCheckException("", "关键信息丢失，操作失败");
        }
        
        solu.setRuleDtls(rules);
        //add by wangdong 重载原有方法，增加删除缓存逻辑，通用
        //boolean ret = ssTransBasicSoluManager.modifyBySeqAndIntTxnCd(solu, gopayIntTxnCd,SolutionTypeConstant.TRANS_BASIC,prodCode);
        boolean ret = ssTransBasicSoluManager.modifyBySeqAndIntTxnCd(solu, gopayIntTxnCd);
        cacheCleanService.cleanCache(new CacheClean(FastJsonUtil.getKey(redisConstants.getRedisEnvironment(), Constants.CACHE_CHANNEL_SOLUTION, prodCode, gopayIntTxnCd, SolutionTypeConstant.TRANS_BASIC)));
        if(!ret) {
            throw new GopayCheckException("", "修改交集基础方案操作失败");
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class, RuntimeException.class })
    public void editSsTbSolution(long solutionId, String gopayIntTxnCd, List<SolutionRuleDtl> rules,String prodCode,String acctId) throws GopayCheckException {

        if(solutionId < 0 || StringUtils.isEmpty(gopayIntTxnCd) || rules == null) {
            throw new GopayCheckException("", "传入数据有误，操作失败");
        }

        Solution solu = ssTransBasicSoluManager.loadBySeqAndIntTxnCd(solutionId, gopayIntTxnCd);
        if(solu == null) {
            throw new GopayCheckException("", "关键信息丢失，操作失败");
        }

        solu.setRuleDtls(rules);
        //add by wangdong 增加删除缓存逻辑，个性化
        //boolean ret = cleanBasicCacheByField(solu, gopayIntTxnCd, SolutionTypeConstant.TRANS_BASIC, prodCode, acctId);
        boolean ret = ssTransBasicSoluManager.modifyBySeqAndIntTxnCd(solu, gopayIntTxnCd);
        cacheCleanService.cleanCache(new CacheClean(FastJsonUtil.getKey(redisConstants.getRedisEnvironment(), Constants.CACHE_CHANNEL_SOLUTION, prodCode, gopayIntTxnCd, SolutionTypeConstant.TRANS_BASIC), acctId));
        if(!ret) {
            throw new GopayCheckException("", "修改交集基础方案操作失败");
        }
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class, RuntimeException.class })
    public void saveSsTbSolution(Solution solu, String gopayIntTxnCd, OprLevel oprLevel, String oprKey,String prodCode)
            throws GopayCheckException {
        if(StringUtils.isEmpty(oprKey) || StringUtils.isEmpty(gopayIntTxnCd) || solu == null) {
            throw new GopayCheckException("", "传入数据有误，操作失败");
        }
        //-----------------先保存关系
        //如果是账户产品级
        if(OprLevel.PROD == oprLevel) {
            
            SsApSolutionRel rel = ssApSolutionRelDAO.getByApIdAndSoluType(oprKey, SolutionTypeConstant.TRANS_BASIC);
            if(rel == null) {
                rel = new SsApSolutionRel();
                rel.setSq(System.currentTimeMillis());
                rel.setProdCode(oprKey);
                rel.setSolutionId(solu.getMeta().getSolutionId());
                rel.setSolutionType(SolutionTypeConstant.TRANS_BASIC);
                rel.setCreatedTs(DateUtils.getSystemDate());
                rel.setLastUpdTs(DateUtils.getSystemDate());
                rel.setLastUpdTranCode("");
                
                //保存关系
                ssApSolutionRelDAO.save(rel);
            }
        } 
        //如果是账户级别
        else if(OprLevel.ACCT == oprLevel) {
            
            SsAcctSolutionRel rel = ssAcctSolutionRelDAO.getByAcctIdAndSoluType(oprKey, SolutionTypeConstant.TRANS_BASIC);
           //add by zhuliang at 2016-4-6 begin
            boolean txnCdisExist = false;
            if(rel != null) {
                Solution solution = ssTransBasicSoluManager.loadBySeqAndIntTxnCd(rel.getSolutionId(), gopayIntTxnCd);
                if(solution != null && solution.getRuleDtls() != null && solution.getRuleDtls().size() > 0) {
                    txnCdisExist = true;
                }
            }
            
            if(!txnCdisExist&&rel!=null){
                solu.getMeta().setSolutionId(rel.getSolutionId());
            }
          //add by zhuliang at 2016-4-6 end
            if(rel == null) {
                rel = new SsAcctSolutionRel();
                rel.setSq(System.currentTimeMillis());
                rel.setAcctId(oprKey);
                rel.setSolutionId(solu.getMeta().getSolutionId());
                rel.setSolutionType(SolutionTypeConstant.TRANS_BASIC);
                rel.setCreatedTs(DateUtils.getSystemDate());
                rel.setLastUpdTs(DateUtils.getSystemDate());
                rel.setLastUpdTranCode("");
                
                //保存关系
                ssAcctSolutionRelDAO.save(rel);
            }
            
        }
        
        //------------再保存方案
        Solution local = ssTransBasicSoluManager.load(solu.getMeta().getSolutionId());
        //如果local==null,表示该方案不存在，需要新建方案和方案与账户产品/账户的关系。 
        if(local == null) {
            //保存方案
            ssTransBasicSoluManager.save(solu);
        }else {
            //如果不为空，表示该方案和方案与账户产品的关系已存在，只需要保存本次传入的方案明细即可
            local.setRuleDtls(solu.getRuleDtls());
            //ssTransBasicSoluManager.modifyBySeqAndIntTxnCd(local, gopayIntTxnCd,SolutionTypeConstant.TRANS_BASIC,prodCode);
            ssTransBasicSoluManager.modifyBySeqAndIntTxnCd(local,gopayIntTxnCd);
            cacheCleanService.cleanCache(new CacheClean(FastJsonUtil.getKey(redisConstants.getRedisEnvironment(), Constants.CACHE_CHANNEL_SOLUTION, prodCode, gopayIntTxnCd, SolutionTypeConstant.TRANS_BASIC)));
        }
    }

    /**
     * 根据field精确清理缓存
     * @param solu
     * @param gopayIntTxnCd
     * @param solutionType
     * @param prodCode
     * @param acctId
     */
    private boolean cleanBasicCacheByField(Solution solu, String gopayIntTxnCd, String solutionType, String prodCode, String acctId){
        String key="";
        boolean ret = false;
        try {
            key = FastJsonUtil.getKey(redisConstants.getRedisEnvironment(), Constants.CACHE_CHANNEL_SOLUTION, prodCode, gopayIntTxnCd, solutionType);
            Long hdel = RedisClient.hdel(key, acctId);
            if (hdel!=null && hdel==1){
                logger.info("======>基础方案个性化，第一次清理缓存成功，key为 {}，field为 {}",key,acctId);
            }else{
                logger.info("======>基础方案个性化，第一次数据不存在或清理失败，key为 {}，field为 {}",key,acctId);
            }
            ret = ssTransBasicSoluManager.modifyBySeqAndIntTxnCd(solu, gopayIntTxnCd);
        } catch (Exception e) {
            logger.error("=====>个性化基础方案缓存清理异常：" , e);
        } finally {
            Long hdel = RedisClient.hdel(key, acctId);
            if (hdel!=null && hdel==1){
                logger.info("======>基础方案个性化，第二次清理缓存成功，key为 {}，field为 {}",key,acctId);
            }else{
                logger.info("======>基础方案个性化，第二次数据不存在或清理失败，key为 {}，field为 {}",key,acctId);
            }
        }
        return ret;
    }

}
